package com.xyzwps.collections.stack

import static org.junit.jupiter.api.Assertions.*

/**
 * This class is used to test common properties of implementations of Stack.
 */
class TestStack {

    static def "case - push and clear"(Stack<Integer> stack) {
        final int MAX = 3242
        assertTrue stack.isEmpty()
        assertFalse stack.isNotEmpty()

        for (def i = 1; i <= MAX; i++) {
            assertEquals stack.push(i), i
            assertEquals stack.size(), i
            assertTrue stack.isNotEmpty()
            assertFalse stack.isEmpty()
        }

        stack.clear()
        assertTrue stack.isEmpty()
        assertFalse stack.isNotEmpty()
    }

    static def "case - push and pop and contains"(Stack<Integer> stack) {
        final int MAX = 12345

        assertTrue stack.isEmpty()
        assertFalse stack.isNotEmpty()
        assertThrows IllegalStateException.class, () -> stack.pop()

        // push
        for (def i = 1; i <= MAX; i++) {
            assertEquals stack.push(i), i
            assertEquals stack.size(), i
            assertTrue stack.isNotEmpty()
            assertFalse stack.isEmpty()
        }

        // contains
        for (int i = -324; i < MAX + 232; i++) {
            if (i < 1) {
                assertFalse stack.has(i)
                assertFalse i in stack
            } else if (i <= MAX) {
                assertTrue stack.has(i)
                assertTrue i in stack
            } else {
                assertFalse stack.has(i)
                assertFalse i in stack
            }
        }

        // pop
        for (def i = MAX; i >= 1; i--) {
            assertTrue stack.isNotEmpty()
            assertFalse stack.isEmpty()
            assertEquals stack.size(), i
            assertEquals stack.pop(), i
        }

        // contains
        for (int i = -324; i < MAX + 232; i++) {
            assertFalse stack.has(i)
            assertFalse i in stack
        }

        assertTrue stack.isEmpty()
        assertFalse stack.isNotEmpty()

        assertThrows IllegalStateException.class, () -> stack.pop()
    }

    static void testCommon(Stack<Integer> stack) {
        "case - push and clear" stack
        "case - push and pop and contains" stack
    }
}
